package com.wolfpire.video.controller;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.wolfpire.system.common.Constants;
/**
 * 视频转码工具类
 * @author xp
 *
 */
public class VideoConverter {  
   // private final static String FLV_PATH = Constants.FILE_ROOT_PATH + "\\";
    private final static String TOOLS_PATH = Constants.FILE_ROOT_PATH;       //工具目录
 //   private static String PATH = "";  
    private static String FILE_NAME = "";   
    
    //原始文件 
    private static String PATH; 
    //目标文件 
    private static String FLV_PATH; 
    
    public VideoConverter(String videoPath , String targetPath){ 
        this.PATH=videoPath; 
        this.FLV_PATH=targetPath; 
        FILE_NAME = videoPath.substring(videoPath.lastIndexOf("\\")+1);
      } 
    
    private static final Log log = LogFactory.getLog(VideoConverter.class);  
    public static String convert(String filePath) {  
            PATH = filePath;  
            FILE_NAME = filePath.substring(filePath.lastIndexOf("\\")+1);
            if(log.isDebugEnabled()){  
                    log.debug("start to convert video to flv format...");  
                    log.debug("the file name is : " + FILE_NAME);  
                    log.debug("the file path is : " + PATH);  
            }  
            if (!checkfile(PATH)) {  
                    return null;  
            } else {  
            	return process();
                    /*if (process()) {  
                            if(log.isDebugEnabled()){  
                                    log.debug("process() ok");  
                            }  
                            return true;  
                    } else {  
                            return false;  
                    }  */
            }  
    }  

    public static String process() {  
            int type = checkContentType();  
            String status = "";  
            if (type == 0) {  
                    if(log.isDebugEnabled()){  
                            log.debug("Start to convert to flv file");  
                    }  
                    status = processMP4(PATH);// 直接将文件转为mp4文件  
            } else if (type == 1) {  
                    String avifilepath = processAVI(type);  
                    if (avifilepath == null){  
                            return "";// avi文件没有得到  
                    }  
                    status = processMP4(avifilepath);// 将avi转为mp4  
            } else if(type == 9){  
                    if(log.isDebugEnabled()){  
                            log.debug("this file is no need to convert.");  
                    }  
                    return "";  
            }  
            return status;  
    }  

    private static int checkContentType() {  
            String type = PATH.substring(PATH.lastIndexOf(".") + 1, PATH.length())  
                            .toLowerCase();  
            // ffmpeg能解析的格式：（asx，asf，mpg，wmv，3gp，mp4，mov，avi，flv等）  
            if (type.equals("avi")) {  
                    return 0;  
            } else if (type.equals("mpg")) {  
                    return 0;  
            } else if (type.equals("wmv")) {  
                    return 0;  
            } else if (type.equals("3gp")) {  
                    return 0;  
            } else if (type.equals("mov")) {  
                    return 0;  
            } else if (type.equals("mp4")) {  
                    return 0;  
            } else if (type.equals("asf")) {  
                    return 0;  
            } else if (type.equals("asx")) {  
                    return 0;  
            } else if (type.equals("flv")) {  
                    return 0;  
            }  
            // 对ffmpeg无法解析的文件格式(wmv9，rm，rmvb等),  
            // 可以先用别的工具（mencoder）转换为avi(ffmpeg能解析的)格式.  
            else if (type.equals("wmv9")) {  
                    return 1;  
            } else if (type.equals("rm")) {  
                    return 1;  
            } else if (type.equals("rmvb")) {  
                    return 1;  
            }  
            return 9;  
    }  

    // check file  
    private static boolean checkfile(String path) {  
            File file = new File(path);  
            if (!file.isFile()) {  
                    return false;  
            }  
            return true;  
    }  

    // 对ffmpeg无法解析的文件格式(wmv9，rm，rmvb等), 可以先用别的工具（mencoder）转换为avi(ffmpeg能解析的)格式.  
    private static String processAVI(int type) {  
            List<String> commend = new ArrayList<String>();  
            //commend.add(FLV_PATH + "/mencoder"); 
            commend.add(TOOLS_PATH + "\\mencoder");  
            commend.add(PATH);  
            commend.add("-oac");  
            commend.add("lavc");  
            commend.add("-lavcopts");  
            commend.add("acodec=mp3:abitrate=64");  
            commend.add("-ovc");  
            commend.add("xvid");  
            commend.add("-xvidencopts");  
            commend.add("bitrate=600");  
            commend.add("-of");  
            commend.add("avi");  
            commend.add("-o");  
            commend.add(FLV_PATH + FILE_NAME.substring(0,FILE_NAME.lastIndexOf(".")) + ".avi");  
            try {  
                    ProcessBuilder builder = new ProcessBuilder();  
                    builder.command(commend);  
                    builder.start();  
                    return FLV_PATH + FILE_NAME.substring(0,FILE_NAME.lastIndexOf(".")) + ".avi";  
            } catch (Exception e) {  
                    e.printStackTrace();  
                    return null;  
            }  
    }  

    // ffmpeg能解析的格式：（asx，asf，mpg，wmv，3gp，mp4，mov，avi，flv等）  
    private static String processFLV(String oldfilepath) {  
            if (!checkfile(PATH)) {  
                    return null;  
            }  
            List<String> commend = new ArrayList<String>();  
            commend.add(TOOLS_PATH + "\\ffmpeg");  
            commend.add("-i");  
            commend.add(oldfilepath);  
            commend.add("-ab");  
            commend.add("56");  
            commend.add("-ar");  
            commend.add("22050");  
            commend.add("-qscale");  
            commend.add("8");  
            commend.add("-r");  
            commend.add("15");  
            commend.add("-s");  
            commend.add("600x500");  
            commend.add(FLV_PATH + FILE_NAME.substring(0,FILE_NAME.lastIndexOf(".")) + ".flv");  
            try {  
                    Runtime runtime = Runtime.getRuntime();  
                    String cmd = "";  
                    String cut = TOOLS_PATH + "\\ffmpeg.exe -i "  
                                    + oldfilepath  
                                    + " -y -f image2 -ss 8 -t 0.001 -s 600x500 "  
                                    + FLV_PATH  
                                    + FILE_NAME.substring(0,FILE_NAME.lastIndexOf("."))  
                                    + ".jpg";  
                    String cutCmd = cmd + cut;  
                    runtime.exec(cutCmd);  
                    ProcessBuilder builder = new ProcessBuilder(commend);  
                    builder.command(commend);  
                    Process process = builder.start();  
                    int i = doWaitFor(process);  
                    if(i == 0){  
                            if(log.isDebugEnabled()){  
                                    log.debug("ffmpeg has finished.");  
                            }  
                    }  
                    return FLV_PATH + FILE_NAME.substring(0,FILE_NAME.lastIndexOf(".")) + ".flv";  
            } catch (Exception e) {  
                    e.printStackTrace();  
                    return null;  
            }  
    } 
    
    private static String processMP4(String oldfilepath) {  
    	 if (!checkfile(PATH)) {  
             return null;  
     }  
     List<String> commend = new ArrayList<String>();  
     commend.add(TOOLS_PATH + "\\ffmpeg");  
     commend.add("-i");  
     commend.add(oldfilepath);  
     commend.add("-ab");  
     commend.add("56");  
     commend.add("-ar");  
     commend.add("44100");  
     commend.add("-qscale");  
     commend.add("8");  
     commend.add("-r");  
     commend.add("15");  
     commend.add("-s");  
     commend.add("800x600");  
     commend.add(FLV_PATH + FILE_NAME.substring(0,FILE_NAME.lastIndexOf(".")) + ".mp4");  
     try {  
             Runtime runtime = Runtime.getRuntime();  
             String cmd = "";  
             String cut = TOOLS_PATH + "\\ffmpeg.exe -i "  
                             + oldfilepath  
                             + " -y -f image2 -ss 8 -t 0.001 -s 800x600 "  
                             + FLV_PATH  
                             + FILE_NAME.substring(0,FILE_NAME.lastIndexOf("."))  
                             + ".jpg";  
             String cutCmd = cmd + cut;  
             runtime.exec(cutCmd);  
             ProcessBuilder builder = new ProcessBuilder(commend);  
             builder.command(commend);  
             Process process = builder.start();  
             int i = doWaitFor(process);  
             if(i == 0){  
                     if(log.isDebugEnabled()){  
                             log.debug("ffmpeg has finished.");  
                     }  
             }  
             return FLV_PATH + FILE_NAME.substring(0,FILE_NAME.lastIndexOf(".")) + ".mp4";  
     } catch (Exception e) {  
             e.printStackTrace();  
             return null;  
     }  
}  
      
    public static int doWaitFor(Process p) {  
     int exitValue = -1; // returned to caller when p is finished  
     try {  
        InputStream in = p.getInputStream();  
        InputStream err = p.getErrorStream();  
        boolean finished = false; // Set to true when p is finished  

        while(!finished){  
        try {  
            while( in.available() > 0) {  
                // Print the output of our system call  
                Character c = new Character( (char) in.read());  
                if(log.isDebugEnabled()){  
                        log.debug( c);  
                }  
            }  
            while( err.available() > 0) {  
                // Print the output of our system call  
                Character c = new Character( (char) err.read());  
                if(log.isDebugEnabled()){  
                        log.debug( c);  
                }  
            }  

            // Ask the process for its exitValue. If the process  
            // is not finished, an IllegalThreadStateException  
            // is thrown. If it is finished, we fall through and  
            // the variable finished is set to true.  
            exitValue = p.exitValue();  
            finished = true;  
        } catch (IllegalThreadStateException e) {  
            Thread.currentThread();  
                    // Process is not finished yet;  
            // Sleep a little to save on CPU cycles  
            Thread.sleep(500);  
        }  
        }  
     } catch (Exception e) {  
        // unexpected exception! print it out for debugging...  
             if(log.isErrorEnabled()){  
                     log.error("doWaitFor(): unexpected exception - " + e.getMessage());  
             }  
        if(log.isErrorEnabled()){  
                log.error(e.getMessage());  
        }  
     }  
     // return completion status to caller  
     return exitValue;  
    }  
    /**
     * 返回图片的地址
     * @param veido_path  视频的地址
     * @return
     */
    public static String processImg(String veido_path){
    	File file = new File(veido_path);  
        if (!file.exists()) {  
        	System.err.println("路径[" + veido_path + "]对应的视频文件不存在!");  
        	return "";  
        }  
        List<String> commands = new java.util.ArrayList<String>();  
        commands.add(TOOLS_PATH + "\\ffmpeg.exe");  
        commands.add("-i");  
        commands.add(veido_path);  
        commands.add("-y");  
        commands.add("-f");  
        commands.add("image2");  
        commands.add("-ss");  
        commands.add("8");//这个参数是设置截取视频多少秒时的画面  
        //commands.add("-t");  
        //commands.add("0.001");  
        commands.add("-s");  
        commands.add("700x525");  
        commands.add(veido_path.substring(0, veido_path.lastIndexOf(".")) + ".jpg");  
        try {  
        ProcessBuilder builder = new ProcessBuilder();  
        builder.command(commands);  
        builder.start();  
        System.out.println("截取成功");  
        return veido_path.substring(0, veido_path.lastIndexOf(".")) + ".jpg";  
        } catch (Exception e) {  
        	e.printStackTrace();  
        	return "";  
        }  
    }
}  